package core;

import gui.GUI;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Random;
import java.util.Scanner;
import java.util.Vector;

import model.proto_main;

import data.Battler;
import data.Database;
import data.Map;

public class Main {
	private static final boolean DEBUG = false;
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		proto_main main = new proto_main();
	}
	
	/* Initialization */
	public Main() {
		Database.init();
	}
	
	private User user;
	
	private PrintStream out = System.out;
	private Scanner in = new Scanner (System.in);
	private enum STATE {
		EXIT,RETURN,RETRY,NEWGAME,OLDGAME,HOME,INFO,DECK,FORMDECK,START,CHECKIN,BATTLE,LOTTERY,ZERO;
	}
	/* Simple User Interface */
	private void ui() throws IOException {
		new GUI();
		STATE nextState = STATE.CHECKIN;
		while(nextState != STATE.ZERO) {
			switch(nextState) {
			case CHECKIN:
				nextState = checkAcc();
				break;
			case START:
				nextState = startGame();
				break;
			case NEWGAME:
				nextState = newGame();
				break;
			case OLDGAME:
				nextState = oldGame();
				break;
			case EXIT:
				nextState = exit();
				break;
			case HOME:
				nextState = home();
				break;
			case INFO:
				//nextState = userinfo();
				break;
			case DECK:
				nextState = cardlist();
				break;
			case BATTLE:
				//nextState = battle();
				break;
			case LOTTERY:
				nextState = lottery();
				break;
			default:
				break;
			}
		}
		out.println("Good Bye");
	}
	private STATE exit() {
		out.println("Game exits");
		return STATE.ZERO;
	}
	private STATE lottery() {
		if (user.rp < 1) {
			out.println("You use up your roll point");
		} else if (user.cardlist.size() > 199){
			out.println("Card list is full");
		} else {
			user.rp--;
			out.println("You get "+user.getCard().name);
			out.println("You have "+user.rp+" roll point left");
		} 
		return STATE.HOME;
	}
	private STATE checkAcc() throws IOException {
		
		
		File file = new File("User");
		BufferedReader reader = null;
		if (file.exists()) {
			reader = new BufferedReader(new FileReader(file));
			String tempString, username = "", password = "";
			int line = 0;
			while ((tempString = reader.readLine()) != null && line < 2) {
				if(line == 0) username = tempString;
				if(line == 1) password = tempString;
                line++;
            }
            reader.close();
            if (line == 2) {
        		user = new User(username, password);
        		user.newdata();
            	return STATE.HOME;
            }
		}
		return STATE.EXIT;
	}
	private STATE startGame() {
		out.println("Game starts");
		out.println("Choose your option:");
		out.println("0: New Game");
		out.println("1: Continue");
		out.println("2: Exit");
		out.print("> ");
		switch (option()){
		case 0:
			return STATE.NEWGAME;
		case 1:
			return STATE.OLDGAME;
		case 2:
			return STATE.EXIT;
		default:
			out.println("[WARNING] Invalid Option\nSystem Exit");
			return STATE.EXIT;
		}
	}

	private STATE newGame() {
		out.println("Welcome");
		String username = "", password = "";
		Connection connex = Database.load("standard.db");
		for (;;) {
			out.println("Please enter your name and your password to create a new account");
			out.print("username:");
			username = in.nextLine();
			out.print("password:");
			password = in.nextLine();
			if (User.register(connex, username, password)) {
				out.println("Successfully register username");
				break;
			} else {
				out.println("User exists. Please enter another username");
			}
		}
		try {
			connex.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		user = new User(username, password);
		user.newdata();
		return STATE.HOME;
	}
	
	private STATE oldGame() {
		out.println("Welcome back");
		out.println("Please enter your name and your password to resume your advanture");
		out.println("username:");
		String username = DEBUG ? "Vapto Duracain" : in.nextLine();
		out.println("password:");
		String password = DEBUG ? "12450" : in.nextLine();
		user = new User(username, password);
		if (user.check()) //TODO Not sure whether I should use user to check the username and password.
			return STATE.HOME;
		else {
			out.println("[WARNING] Username and password do not match\nSystem Exit");
			return STATE.EXIT;
		}
	}
	
	private STATE home() {
		out.println("What do you want to do?");
		out.println("0: Show my user info");
		out.println("1: Show my card list");
		out.println("2: Roll");
		out.println("3: Shop");
		out.println("4: Explore");
		out.println("5: Battle");
		out.println("6: Quit");
		out.println("7: Log out");
		out.print("> ");
		switch (option()) {
		case 0:
			out.println("Username: "+user.username);
			out.println("Password: "+user.password);
			out.println("Gold: "+user.gold);
			out.println("Roll Point: "+user.rp);
			out.println("Action Point: "+user.ap);
			return STATE.HOME;
		case 1:
			return cardlist();
		case 2:
			if (user.rp < 1) {
				out.println("You use up your roll point");
			} else if (user.cardlist.size() > 199){
				out.println("Card list is full");
			} else {
				user.rp--;
				out.println("You get "+user.getCard().name);
				out.println("You have "+user.rp+" roll point left");
			} 
			return STATE.HOME;
		case 3:
			if (user.gold < 100) {
				out.println("You do not have enough gold");
			} else {
				user.gold -= 100;
				out.println("You have "+user.gold+" gold left");
			}
			return STATE.HOME;
		case 4:
			return explore();
		case 5:
			if (user.inBattle) {
				out.println("Battle resumes");
				battle();
			} else {
				out.println("You are not in battle");
			}
			return STATE.HOME;
		case 6:
			out.println("Good bye");
			out.println("Game exits");
			return STATE.EXIT;
		case 7:
			return STATE.CHECKIN;
		default:
			out.println("[WARNING] Invalid Option\nSystem Exit");
			return STATE.EXIT;
		}
		
	}
	private STATE cardlist() {
		out.println("You have following card(s)");
		for (int i = 0;i < user.cardlist.size();i++) {
			out.println(String.format("%d ",i)+user.cardlist.get(i).name);
		}
		out.println("Your deck is: ");
		for (int i = 0;i < user.carddeck.size();i++) {
			out.println(String.format("%d ",i)+user.carddeck.get(i).name);
		}
		out.println("What do you want to do?");
		out.println("0: Exit");
		out.println("1: Make your deck");
		out.println("2: Show your deck");
		switch(option()) {
		case 0:
			/* return to main menu*/
			break;
		case 1:
			int pos = 0, index = 0;
			for(;;) {
				out.println("Enter the position you want to exchange:");
				pos = option();
				if (pos < 0 || pos > 12) {
					out.println("Nothing is selected. Want to exit? (Y/N)");
					if(yes())
						break;
				} else {
					if (pos < user.carddeck.size() -1) {
						out.println("You selected"+user.carddeck.get(pos));
					} else {
						out.println("Empty position");
					}
					out.println("Enter the card index you want to replace (-1 to abort):");
					index = option();
					if (index > -1 && index < user.cardlist.size()-1) {
						if (pos < user.carddeck.size() -1) {
							user.carddeck.set(pos, user.cardlist.get(index));
						} else {
							user.carddeck.add(user.cardlist.get(index));
						}
					}
					out.println("Your deck is: ");
					for (int i = 0;i < user.carddeck.size();i++) {
						out.println(String.format("%d ",i)+user.carddeck.get(i).name);
					}
				}
			}
			break;
		default:
		}
		return STATE.HOME;
	}
	private STATE explore() {
		Vector<String> map = new Vector<String>();
		map.add("School");
		map.add("Hospital");
		map.add("Graveyard");
		map.add("Garden");
		map.add("Castle");
		out.println("Where do you want to go?");
		for (int index = 0;index < map.size();index++) {
			out.println(index+": "+map.get(index));
		}
		int opt = 0;
		switch (opt = option()) {
		case 0:
			out.println("You are visiting "+map.get(opt));
			visit();
			break;
		case 1:
			out.println("You are visiting "+map.get(opt));
			visit();
			break;
		case 2:
			out.println("You are visiting "+map.get(opt));
			visit();
			break;
		case 3:
			out.println("You are visiting "+map.get(opt));
			visit();
			break;
		case 4:
			out.println("You are visiting "+map.get(opt));
			visit();
			break;
		default:
			out.println("You decide to go back");
		}
		return STATE.HOME;
	}
	
	private void visit() {
		while (user.ap > 0) {
			out.println("Continue visiting? y/n");
			if (yes()) {
				user.ap --;
				randomEvent();
			} else {
				out.println("You decide to go back");
				return;
			}
		}
		out.println("No more energy\nYou have to go back");
	}
	private void randomEvent() {
		int rst = new Random().nextInt(100);
		Map map = new Map();
		if (rst < map.distribution[0]) {
			/* Recover Action Point */
			int value = map.baseAP+rst;
			user.getAP(value);
			out.println("Your action point recovers "+value);
			
		} else if (rst < map.distribution[1]) {
			/* Gain Gold */
			int value = map.baseGold+rst;
			user.gold = user.gold+value;
			out.println("Your get gold "+value);
			
		} else if (rst < map.distribution[2] && !user.inBattle) {
			/* Encounter Battle */
			out.println("You encounter an enemy");
			user.inBattle = true;
			user.enemy = new Battler(50000, 50000, "Amethust", new int[]{3000,3400,2400,5100});
			battle();
		} else {
			out.println("Nothing happens");
		}
	}
	private void battle() {
		while(true){
			out.println(user.enemy.name);
			out.println("HP:"+user.enemy.curhp+"/"+user.enemy.maxhp);
			out.println("Want to attack? y/n");
			if (yes()) {
				user.player = new Battler(12000, 12000, user.username, new int[]{2700,3100,2000,2100});
				int dam;
				Battler enemy = user.enemy, player = user.player;
				while (enemy.curhp > 0 && player.curhp > 0) {
					dam = player.nextAttack();
					out.println(enemy.name+":"+enemy.curhp+" - "+dam);
					enemy.curhp -= player.nextAttack();
					
					dam = enemy.nextAttack();
					out.println(player.name+":"+player.curhp+" - "+dam);
					player.curhp -= dam;
				}
				if (user.enemy.curhp < 1) {
					out.println("You won");
					user.inBattle = false;
					user.enemy = null;
					break;
				} else {
					out.println("You lost");
				}
			} else {
				out.println("You decide to run");
				break;
			}
		}
	}
	/* -------------------------------------- */
	private int option() {
		int opt = 0;
		if (in.hasNextInt())
			opt = in.nextInt();
		in.nextLine();
		return opt;
	}
	private boolean yes() {
		String opt = in.nextLine();
		return opt.equals("y");
	}
}